<?php

declare(strict_types=1);

namespace App\Controller;

use Hyperf\Apidog\Annotation\ApiController;
use Hyperf\Apidog\Annotation\DeleteApi;
use Hyperf\Apidog\Annotation\PostApi;
use Hyperf\Apidog\Annotation\GetApi;
use Hyperf\Apidog\Annotation\FormData;
use Hyperf\Apidog\Annotation\Query;
use Hyperf\Context\Context;
use Hyperf\Database\Model\Builder;
use App\Model\AdminMenu;
use App\Model\AdminRole;
use App\Model\AdminUser;
use App\Model\Project;
use Carbon\Carbon;

/**
 * @ApiController(prefix="passport", tag="授权登录", server="backend-api")
 */
class PassportController extends AdminController
{
    /**
     * @PostApi(path="login", description="账号密码登录")
     * @FormData(key="username|账号", rule="required")
     * @FormData(key="password|密码，32位md5加密", rule="required")
     */
    public function login()
    {
        $AdminUser = AdminUser::where('username', $this->request->input('username', ''))->first();
        if (!$AdminUser) {
            return [
                'code' => 400,
                'message' => '账号错误',
            ];
        }
        if (!$AdminUser->user_status) {
            return [
                'code' => 400,
                'message' => '此账号已被禁用，请联系系统管理员',
            ];
        }
        $password = strtolower($this->request->input('password', ''));
        if ($AdminUser->password != ($AdminUser->salt ? md5($password . $AdminUser->salt) : $password)) {
            return [
                'code' => 400,
                'message' => '密码错误',
            ];
        }

        //更新最后一次登录信息
        $AdminUser->last_ip = $this->request->getAttribute('client-ip');
        $AdminUser->last_at = Carbon::now()->timestamp;
        $AdminUser->save();

        $token = $this->auth->login($AdminUser);
        return $this->adminResponse(200, '请求成功', [
            'token' => 'Bearer ' . $token,
        ]);
    }

    /**
     * @GetApi(path="my", description="获取登录信息")
     * @Query(key="project_handle|项目唯一标识", rule="")
     */
    public function my()
    {
        $validator_data = Context::get('validator.data');

        $AdminUser = $this->auth->user();
        $AdminRole = AdminRole::where('id', $AdminUser->role_id)->first(['menu_permissions', 'include_sites']);
        if (!$AdminRole) {
            return $this->adminResponse(400, '账号没有绑定角色');
        }

        $ProjectBuilder = Project::query();
        if ($AdminRole->include_sites && ($include_sites = explode(',', $AdminRole->include_sites)) && $include_sites[0]) {
            $AdminRole->include_sites && $ProjectBuilder->whereIn('handle', $include_sites);
        }
        $projects = $ProjectBuilder->get()
            ->toArray();
        $project_handles = array_column($projects, 'handle');
        $project_handle = !empty($validator_data['project_handle']) && in_array($validator_data['project_handle'], $project_handles) ? $validator_data['project_handle'] : ($project_handles ? $project_handles[0] : '');

        $fields = ['id', 'parent_id', 'name', 'route'];
        $menu_permissions = [];
        if ($AdminUser->role_id) {
            $AdminRole = AdminRole::where('id', $AdminUser->role_id)->first(['menu_permissions']);
            $AdminRole && $menu_permissions = $AdminRole->toArray()['menu_permissions'];
        }
        // 菜单树半选状态时，数据上并不包含父级菜单id，但实际上需要展示出来的
        if ($menu_permissions) {
            $ids = [];
            $AdminMenu = AdminMenu::query()
                ->whereIn('id',  $menu_permissions);
            if ($project_handle) {
                $AdminMenu->where(function(Builder $Query) use ($project_handle) {
                    $Query->whereJsonContains('include_sites', [$project_handle], 'or');
                    $Query->whereJsonContains('include_sites', [''], 'or');
                    $Query->whereNull('include_sites', 'or');
                });
                $AdminMenu->where(function(Builder $Query) use ($project_handle) {
                    $Query->whereJsonContains('exclude_sites', [$project_handle], 'or', true);
                    $Query->whereJsonContains('exclude_sites', [''], 'or');
                    $Query->whereNull('exclude_sites', 'or');
                });
            }
            foreach ($AdminMenu->get(['id', 'parent_id'])->toArray() as $menu) {
                $ids[] = $menu['id'];
                $ids[] = $menu['parent_id'];
            }
            $menu_permissions = array_unique($ids);
        }
        $raw = AdminMenu::whereIn('id',  $menu_permissions)->orderBy('parent_id')->orderBy('order')->get($fields)->toArray();
        foreach ($raw as $k => $v) {
            $v = array_merge($v, $v['route']);
            unset($v['route']);

            $raw[$k] = $v;
        }
        $permission_routes = [
            'router' => 'root',
            'children' => AdminMenu::buildTree($raw),
        ];

        // 返回所有菜单
        $routes_raw = AdminMenu::getRaw();
        foreach ($routes_raw as $k => $v) {
            $v = array_merge($v, $v['route']);
            unset($v['route']);

            $routes_raw[$k] = $v;
        }
        $routes = AdminMenu::buildTree($routes_raw);

        // 有传handel，且有这个项目的情况下，把该项目放到第一位
        if ($project_handle) {
            $handle_projects = array_column($projects, null, 'handle');
            $first_project = $handle_projects[$project_handle];
            unset($handle_projects[$project_handle]);
            $projects = array_merge([$first_project], array_values($handle_projects));
        }

        return $this->adminResponse(200, '请求成功', [
            'admin_user' => [
                'username' => $AdminUser->username,
                'name' => $AdminUser->name,
                'avatar' => $AdminUser->avatar,
            ],
            'permission_routes' => $permission_routes,
            'projects' => $projects,
            'routes' => $routes,
        ]);
    }

    /**
     * @DeleteApi(path="logout", description="注销登录")
     */
    public function logout()
    {
        $this->auth->logout();
        return $this->adminResponse(200, '请求成功');
    }
}
